package com.ayz.gateway.center.infrastructure.nginx.Executor;

import com.ayz.gateway.center.infrastructure.nginx.LoadBalanceRule;
import com.ayz.gateway.common.constants.GatewayServiceData;
import com.github.odiszapc.nginxparser.*;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

/**
 * @ClassName GatewayServiceExpose
 * @Description TODO:网关服务暴露
 * 新网关服务上线了 修改其配置文件
 * @Author 快乐的星球
 * @Date 2023/6/12 16:17
 * @Version 1.0
 **/
@Getter
@Setter
public class GatewayServiceExpose {
    private LoadBalanceRule loadBalanceRule;
    public GatewayServiceExpose(LoadBalanceRule loadBalanceRule) {
        this.loadBalanceRule = loadBalanceRule;
    }
    /**
     * 向NGX配置文件中暴露一个网关服务
     * @param gatewayServiceData
     * @param ngxConfig
     */
    public void exposeGatewayService(GatewayServiceData gatewayServiceData,
                                     NgxConfig ngxConfig){
        //1:判断当前网关服务是否是其所属的业务组下第一个网关服务
        String groupName=gatewayServiceData.getGatewayGroup();
        boolean isFirstRegistry=false;
        NgxBlock upStreamBlock=null;

        List<NgxEntry> upstreamList = ngxConfig.findAll(NgxConfig.BLOCK, "upstream");
        if(upstreamList==null || upstreamList.isEmpty()){
            isFirstRegistry=true;
        }else {
            for (NgxEntry entry : upstreamList) {
                NgxBlock block=(NgxBlock) entry;
                String curGroupName = block.getValue();
                if(groupName.equals(curGroupName)){
                    upStreamBlock=block;
                    break;
                }
            }
            if(upStreamBlock==null){
                isFirstRegistry=true;
            }
        }
        //2:根据是否是当前网关业务组下第一个网关服务 完成upstream的编写
        if(isFirstRegistry){
            upStreamBlock=new NgxBlock();
            upStreamBlock.addValue(new NgxToken("upstream"));
            upStreamBlock.addValue(new NgxToken(groupName));
            //添加负载均衡策略
            if(!(loadBalanceRule ==LoadBalanceRule.DEFAULT)){
                //ip_hash or least_conn
                NgxParam loadBalance=new NgxParam();
                loadBalance.addValue(loadBalanceRule.getValue());
                upStreamBlock.addEntry(loadBalance);
            }        //添加网关服务的地址
            NgxParam gatewayServiceAddress=new NgxParam();
            String serverAddress="server "+gatewayServiceData.getAddress();
            gatewayServiceAddress.addValue(serverAddress);
            upStreamBlock.addEntry(gatewayServiceAddress);
            ngxConfig.addEntry(upStreamBlock);
        }else{
            String serverAddress=gatewayServiceData.getAddress();
            List<NgxEntry> serverList = upStreamBlock.findAll(NgxConfig.PARAM, "server");
            //判断是否已经注册过
            boolean registered=false;
            for (NgxEntry serverEntry : serverList) {
                NgxParam server=(NgxParam) serverEntry;
                String address = server.getValue();
                if(serverAddress.equals(address)){
                    registered=true;
                    break;
                }
            }
            if(!registered){
                NgxParam curGatewayServer=new NgxParam();
                curGatewayServer.addValue("server "+serverAddress);
                upStreamBlock.addEntry(curGatewayServer);
            }
        }
        //TODO: 如果当前网关服务是当前网关业务组下第一个网关服务，还需要添加路由映射
        if(isFirstRegistry){
            NgxBlock serverBlock = ngxConfig.findBlock("server");

            NgxBlock routeBlock=new NgxBlock();
            routeBlock.addValue(new NgxToken("location"));
            routeBlock.addValue(new NgxToken("/"+groupName+"/"));

            NgxParam proxyPass=new NgxParam();
            proxyPass.addValue("proxy_pass http://"+groupName);
            routeBlock.addEntry(proxyPass);

            serverBlock.addEntry(routeBlock);
        }
    }
}
